package com.mdxq.mall.listener;

import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.Random;

//@Component
@Slf4j
//消息监听器：监听某个队列，当消息进入队列后执行方法，消费信息
public class MyMessageListener implements ChannelAwareMessageListener {
//    @Autowired
    private ConnectionFactory connectionFactory;
    @Bean/*("containerFactory")*/
    public SimpleRabbitListenerContainerFactory containerFactory(){
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);//设置连续工厂
        factory.setPrefetchCount(1);//一般用于高并发场景下的消息处理，进行流量控制，削峰填谷
        return factory;
    }
    //onMessage是监听方法，新消息到来自动执行
    int N = 3;
    @Override
    @RabbitListener(queues = {"normal_queue"},containerFactory = "containerFactory",ackMode = "MANUAL")
    public void onMessage(Message message, Channel channel) throws Exception {
        String info = "消费者X收到新消息，内容：{}    使用的信道：{}";
        log.info(info,new String(message.getBody(), StandardCharsets.UTF_8),channel.getChannelNumber());
        //模拟消费者处理消息的过程
        Random random = new Random();
//        boolean x = random.nextBoolean()
        boolean x = false;//随机失败改为必然失败

        try {
            if (x){
                //给MQ返回一个ack的状态码，表示本条消息消费成功，无需重复发送
                channel.basicAck(message.getMessageProperties().getDeliveryTag(),true);
                log.info("这条消息消费成功~~~~~~~");
            }else {
                //模拟消费失败
                log.error("消息的消费失败，需要重发~~~~");
                throw new RuntimeException("模拟异常，消息处理出错");
            }
        }catch (Exception ex){
            log.info(ex.getMessage());
            if (N-- >0){
                channel.basicNack(message.getMessageProperties().getDeliveryTag(),true,true);
            }else {
                channel.basicNack(message.getMessageProperties().getDeliveryTag(),true,false);
            }
        }
    }
}
